package jtools

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"path/filepath"
	"strconv"

	"gitee.com/liaojin0910/jtools/models"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)

type webTest struct {
	R *http.Request
	W *httptest.ResponseRecorder
}

func (wt *webTest) set(req *http.Request, res *httptest.ResponseRecorder) {
	wt.R = req
	wt.W = res
}

func (wt *webTest) Run(f func(w *httptest.ResponseRecorder)) {
	r.ServeHTTP(wt.W, wt.R)
	f(wt.W)
}

func (wt *webTest) SetHeader(k, v string) *webTest {
	wt.R.Header.Add(k, v)
	return wt
}

func (wt *webTest) AddFile(uploadName, filePath string) *webTest {
	file, err := os.Open(filePath)
	if err != nil {
		panic(err)
	}
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(uploadName, filepath.Base(filePath))
	if err != nil {
		panic(err)
	}
	_, err = io.Copy(part, file)
	if err != nil {
		panic(err)
	}
	writer.Close()
	wt.R.Body = io.NopCloser(body)
	wt.R.Header.Add("Content-Type", writer.FormDataContentType())

	return wt
}

func (wt *webTest) SetJson(jsonData []byte) *webTest {
	wt.R.Body = io.NopCloser(bytes.NewReader(jsonData))
	return wt
}

func (wt *webTest) SetForm(form url.Values) *webTest {
	wt.R.PostForm = form
	return wt
}

var r *gin.Engine

// func init() {
// 	r = bootstrap.MakeGin("../.env")
// }

func InitTest(eng *gin.Engine) {
	r = eng
}

func InitValidator() {
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("runeMax", runeMax)
		v.RegisterValidation("cn_phone", models.VMobile)
		v.RegisterValidation("cn_gte", models.VCnGte)
		v.RegisterValidation("cn_lte", models.VCnLte)
		v.RegisterValidation("l_datetime", models.VTime)
		v.RegisterValidation("l_dateonly", models.VDateOnly)
	}
}

func MakeWebTest(p string, path string) *webTest {
	res := httptest.NewRecorder()
	req, _ := http.NewRequest(p, path, nil)
	wt := webTest{}
	wt.set(req, res)
	return &wt
}

func runeMax(fl validator.FieldLevel) bool {

	n, err := strconv.Atoi(fl.Param())
	if err != nil {
		return true
	}

	if len([]rune(fl.Field().String())) > n {
		return false
	}

	return true

}

// func testTeacherList(t *testing.T) {
// 	makeWebTest("GET", "/xxx/list").run(func(w *httptest.ResponseRecorder) {
// 		assert.Equal(t, 200, w.Code)
// 		t.Log(w.Body.String())
// 	})
// }

// func testTeacherAdd(t *testing.T) {
// 	f := make(url.Values)
// 	f.Add("username", "")
// 	f.Add("password", "hello")

// 	makeWebTest("POST", "/xxx/add").setForm(f).run(func(w *httptest.ResponseRecorder) {
// 		assert.Equal(t, 200, w.Code)
// 		t.Log(w.Body.String())
// 	})

// }

// func TestJsonAdd(t *testing.T) {
// 	m := make(map[string]interface{})
// 	m["s"] = 37

// 	j, _ := json.Marshal(m)

// 	makeWebTest("POST", "/v1/json").setHeader("Content-Type", "application/json;charset=UTF-8").setJson(j).run(func(w *httptest.ResponseRecorder) {

// 		t.Log(w.Body.String())
// 	})

// }
